﻿using Org.BouncyCastle.Crypto;
using System.Text.Json;
using System.Text;

namespace LicenseDemo.Licenses;

/// <summary>
/// license 授权助手
/// </summary>
/// <param name="publicKey">公钥</param>
/// <param name="privateKey">私钥</param>
class LicenseAssistant(AsymmetricCipherKeyPair keyPair)
{
    private readonly Sm2Assistant _sm2Assistant = new();

    private AsymmetricKeyParameter PublicKey => keyPair.Public;
    private AsymmetricKeyParameter PrivateKey => keyPair.Private;

    /// <summary>
    /// 生成License文件(.lic授权证书)
    /// </summary>
    /// <param name="licenseData"></param>
    /// <param name="outputFile"></param>
    /// <returns></returns>
    public async Task GenerateLicenseFileAsync(LicenseData licenseData, string outputFile)
    {
        // 序列化数据
        string jsonString = await JsonSerializeAsync(licenseData);

        // 对数据进行签名
        byte[] dataToSign = Encoding.UTF8.GetBytes(jsonString);
        byte[] signature = _sm2Assistant.SignData(dataToSign, PrivateKey);

        // 组合数据和签名
        LicenseContent licenseContent = new()
        {
            Data = jsonString,
            Signature = Convert.ToBase64String(signature)
        };

        // 异步序列化 JSON 数据
        string license = await JsonSerializeAsync(licenseContent);

        // 公钥加密
        string licenseCiphertext = _sm2Assistant.Encrypt(license, PublicKey);

        // 写入文件
        await File.WriteAllTextAsync(outputFile, licenseCiphertext);
    }

    /// <summary>
    /// 验证License文件(.lic授权证书)
    /// </summary>
    /// <param name="licenseFilePath"></param>
    /// <returns></returns>
    public async Task<bool> VerifyLicenseFileAsync(string licenseFilePath)
    {
        // 读取文件内容
        string licenseCiphertext = await File.ReadAllTextAsync(licenseFilePath);

        // 私钥解密
        string licenseContent = _sm2Assistant.Decrypt(licenseCiphertext, PrivateKey);

        // 异步反序列化 JSON 数据
        var licenseData = await JsonDeserializeAsync<LicenseContent>(licenseContent);

        // 解析数据和签名
        string data = licenseData.Data;
        byte[] signature = Convert.FromBase64String(licenseData.Signature);

        // 验证签名
        byte[] verify = Encoding.UTF8.GetBytes(data);
        return _sm2Assistant.VerifyData(verify, signature, PublicKey);
    }

    /// <summary>
    /// 序列化数据
    /// </summary>
    /// <typeparam name="TData"></typeparam>
    /// <param name="data"></param>
    /// <returns></returns>
    private async Task<string> JsonSerializeAsync<TData>(TData data)
    {
        using var stream = new MemoryStream();
        await JsonSerializer.SerializeAsync(stream, data);

        stream.Position = 0;
        using var reader = new StreamReader(stream);
        return await reader.ReadToEndAsync();
    }

    /// <summary>
    /// 反序列化数据
    /// </summary>
    /// <typeparam name="TData"></typeparam>
    /// <param name="data"></param>
    /// <returns></returns>
    private async Task<TData> JsonDeserializeAsync<TData>(string data)
    {
        if (string.IsNullOrWhiteSpace(data))
            return default!;

        // 解析数据和签名
        byte[] jsonBytes = Encoding.UTF8.GetBytes(data);
        using var stream = new MemoryStream(jsonBytes);

        // 将 JSON 字符串写入内存流
        //await stream.WriteAsync(jsonBytes, 0, jsonBytes.Length);
        //stream.Position = 0;

        // 异步反序列化 JSON 数据
        return await JsonSerializer.DeserializeAsync<TData>(stream);
    }

}
